home *** CD-ROM | disk | FTP | other *** search
- { Created : 1994-06-23 (c) Copyright 1994 by Berend de Boer
-
- Unit to facilitate ports of Dos/DPMI objects to Windows. The object created here
- initializes all fields to zero, just as the Dos TObject.
-
- And it implements TResourceFile which was for some reason(??) missing in
- the windows version of Objects
-
-
- Last changes :
- }
-
-
-
- {$IFDEF DPMI}
- {$X+,S-}
- {$ELSE}
- {$X+,F+,O+}
- {$ENDIF}
- unit BBObject;
-
- interface
-
- {$IFDEF Windows}
- uses Objects;
-
-
- type
- TObject = object(Objects.TObject)
- constructor Init;
- end;
-
-
- { Private resource manager types }
-
- const
- RStreamMagic: Longint = $52504246; { 'FBPR' }
- RStreamBackLink: Longint = $4C424246; { 'FBBL' }
-
- type
- PResourceItem = ^TResourceItem;
- TResourceItem = record
- Pos: Longint;
- Size: Longint;
- Key: String;
- end;
-
- { TResourceCollection object }
-
- PResourceCollection = ^TResourceCollection;
- TResourceCollection = object(TStringCollection)
- procedure FreeItem(Item: Pointer); virtual;
- function GetItem(var S: TStream): Pointer; virtual;
- function KeyOf(Item: Pointer): Pointer; virtual;
- procedure PutItem(var S: TStream; Item: Pointer); virtual;
- end;
-
- { TResourceFile object }
-
- PResourceFile = ^TResourceFile;
- TResourceFile = object(TObject)
- Stream: PStream;
- Modified: Boolean;
- constructor Init(AStream: PStream);
- destructor Done; virtual;
- function Count: Integer;
- procedure Delete(Key: String);
- procedure Flush;
- function Get(Key: String): PObject;
- function KeyAt(I: Integer): String;
- procedure Put(Item: PObject; Key: String);
- function SwitchTo(AStream: PStream; Pack: Boolean): PStream;
- private
- BasePos: Longint;
- IndexPos: Longint;
- Index: TResourceCollection;
- end;
-
- {$ENDIF}
-
-
-
- implementation
-
-
- {$IFDEF Windows}
- constructor TObject.Init;
- type
- Image = record
- Link: Word;
- Data: record end;
- end;
- begin
- FillChar(Image(Self).Data, SizeOf(Self) - SizeOf(TObject), 0);
- inherited Init;
- end;
-
-
- { TResourceCollection }
-
- procedure TResourceCollection.FreeItem(Item: Pointer);
- begin
- FreeMem(Item, Length(PResourceItem(Item)^.Key) +
- (SizeOf(TResourceItem) - SizeOf(String) + 1));
- end;
-
- function TResourceCollection.GetItem(var S: TStream): Pointer;
- var
- Pos: Longint;
- Size: Longint;
- L: Byte;
- P: PResourceItem;
- begin
- S.Read(Pos, SizeOf(Longint));
- S.Read(Size, SizeOf(Longint));
- S.Read(L, 1);
- GetMem(P, L + (SizeOf(TResourceItem) - SizeOf(String) + 1));
- P^.Pos := Pos;
- P^.Size := Size;
- P^.Key[0] := Char(L);
- S.Read(P^.Key[1], L);
- GetItem := P;
- end;
-
- function TResourceCollection.KeyOf(Item: Pointer): Pointer; assembler;
- asm
- MOV AX,Item.Word[0]
- MOV DX,Item.Word[2]
- ADD AX,OFFSET TResourceItem.Key
- end;
-
- procedure TResourceCollection.PutItem(var S: TStream; Item: Pointer);
- begin
- S.Write(PResourceItem(Item)^, Length(PResourceItem(Item)^.Key) +
- (SizeOf(TResourceItem) - SizeOf(String) + 1));
- end;
-
- { TResourceFile }
-
- constructor TResourceFile.Init(AStream: PStream);
- type
-
- {$IFDEF NewExeFormat}
-
- TExeHeader = record
- eHdrSize: Word;
- eMinAbove: Word;
- eMaxAbove: Word;
- eInitSS: Word;
- eInitSP: Word;
- eCheckSum: Word;
- eInitPC: Word;
- eInitCS: Word;
- eRelocOfs: Word;
- eOvlyNum: Word;
- eRelocTab: Word;
- eSpace: Array[1..30] of Byte;
- eNewHeader: Word;
- end;
-
- {$ENDIF}
-
- THeader = record
- Signature: Word;
- case Integer of
- 0: (
- LastCount: Word;
- PageCount: Word;
- ReloCount: Word);
- 1: (
- InfoType: Word;
- InfoSize: Longint);
- end;
- var
- Found, Stop: Boolean;
- Header: THeader;
-
- {$IFDEF NewExeFormat}
-
- ExeHeader: TExeHeader;
-
- {$ENDIF}
-
- begin
- TObject.Init;
- Stream := AStream;
- BasePos := Stream^.GetPos;
- Found := False;
- repeat
- Stop := True;
- if BasePos <= Stream^.GetSize - SizeOf(THeader) then
- begin
- Stream^.Seek(BasePos);
- Stream^.Read(Header, SizeOf(THeader));
- case Header.Signature of
-
- {$IFDEF NewExeFormat}
-
- $5A4D:
- begin
- Stream^.Read(ExeHeader, SizeOf(TExeHeader));
- BasePos := ExeHeader.eNewHeader;
- Stop := False;
- end;
- $454E:
- begin
- BasePos := Stream^.GetSize - 8;
- Stop := False;
- end;
- $4246:
- begin
- Stop := False;
- case Header.Infotype of
- $5250: {Found Resource}
- begin
- Found := True;
- Stop := True;
- end;
- $4C42: Dec(BasePos, Header.InfoSize - 8); {Found BackLink}
- $4648: Dec(BasePos, SizeOf(THeader) * 2); {Found HelpFile}
- else
- Stop := True;
- end;
- end;
- $424E:
- if Header.InfoType = $3230 then {Found Debug Info}
- begin
- Dec(BasePos, Header.InfoSize);
- Stop := False;
- end;
-
- {$ELSE}
-
- $5A4D:
- begin
- Inc(BasePos, LongMul(Header.PageCount, 512) -
- (-Header.LastCount and 511));
- Stop := False;
- end;
- $4246:
- if Header.InfoType = $5250 then Found := True else
- begin
- Inc(BasePos, Header.InfoSize + 8);
- Stop := False;
- end;
-
- {$ENDIF}
-
- end;
- end;
- until Stop;
- if Found then
- begin
- Stream^.Seek(BasePos + SizeOf(Longint) * 2);
- Stream^.Read(IndexPos, SizeOf(Longint));
- Stream^.Seek(BasePos + IndexPos);
- Index.Load(Stream^);
- end else
- begin
- IndexPos := SizeOf(Longint) * 3;
- Index.Init(0, 8);
- end;
- end;
-
- destructor TResourceFile.Done;
- begin
- Flush;
- Index.Done;
- Dispose(Stream, Done);
- end;
-
- function TResourceFile.Count: Integer;
- begin
- Count := Index.Count;
- end;
-
- procedure TResourceFile.Delete(Key: String);
- var
- I: Integer;
- begin
- if Index.Search(@Key, I) then
- begin
- Index.Free(Index.At(I));
- Modified := True;
- end;
- end;
-
- procedure TResourceFile.Flush;
- var
- ResSize: Longint;
- LinkSize: Longint;
- begin
- if Modified then
- begin
- Stream^.Seek(BasePos + IndexPos);
- Index.Store(Stream^);
- ResSize := Stream^.GetPos - BasePos;
- LinkSize := ResSize + SizeOf(Longint) * 2;
- Stream^.Write(RStreamBackLink, SizeOf(Longint));
- Stream^.Write(LinkSize, SizeOf(Longint));
- Stream^.Seek(BasePos);
- Stream^.Write(RStreamMagic, SizeOf(Longint));
- Stream^.Write(ResSize, SizeOf(Longint));
- Stream^.Write(IndexPos, SizeOf(Longint));
- Stream^.Flush;
- Modified := False;
- end;
- end;
-
- function TResourceFile.Get(Key: String): PObject;
- var
- I: Integer;
- begin
- if not Index.Search(@Key, I) then Get := nil else
- begin
- Stream^.Seek(BasePos + PResourceItem(Index.At(I))^.Pos);
- Get := Stream^.Get;
- end;
- end;
-
- function TResourceFile.KeyAt(I: Integer): String;
- begin
- KeyAt := PResourceItem(Index.At(I))^.Key;
- end;
-
- procedure TResourceFile.Put(Item: PObject; Key: String);
- var
- I: Integer;
- P: PResourceItem;
- begin
- if Index.Search(@Key, I) then P := Index.At(I) else
- begin
- GetMem(P, Length(Key) + (SizeOf(TResourceItem) - SizeOf(String) + 1));
- P^.Key := Key;
- Index.AtInsert(I, P);
- end;
- P^.Pos := IndexPos;
- Stream^.Seek(BasePos + IndexPos);
- Stream^.Put(Item);
- IndexPos := Stream^.GetPos - BasePos;
- P^.Size := IndexPos - P^.Pos;
- Modified := True;
- end;
-
- function TResourceFile.SwitchTo(AStream: PStream; Pack: Boolean): PStream;
- var
- NewBasePos: Longint;
-
- procedure DoCopyResource(Item: PResourceItem); far;
- begin
- Stream^.Seek(BasePos + Item^.Pos);
- Item^.Pos := AStream^.GetPos - NewBasePos;
- AStream^.CopyFrom(Stream^, Item^.Size);
- end;
-
- begin
- SwitchTo := Stream;
- NewBasePos := AStream^.GetPos;
- if Pack then
- begin
- AStream^.Seek(NewBasePos + SizeOf(Longint) * 3);
- Index.ForEach(@DoCopyResource);
- IndexPos := AStream^.GetPos - NewBasePos;
- end else
- begin
- Stream^.Seek(BasePos);
- AStream^.CopyFrom(Stream^, IndexPos);
- end;
- Stream := AStream;
- Modified := True;
- BasePos := NewBasePos;
- end;
- {$ENDIF}
-
-
- end. { of unit BBOject }
-